package com.sxt.aspect;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.sxt.anno.ActionLog;
import com.sxt.entity.SysLog;
import com.sxt.entity.SysUser;
import com.sxt.service.SysLogService;

import cn.hutool.json.JSONUtil;

@Aspect
@Component
public class ActionLogAspect {

	@Autowired
	private SysLogService  sysLogService ;
	//execution (* com.sxt.*.*(..))
	@Around("@annotation(com.sxt.anno.ActionLog)")  // 只有添加了@ActionLog的方法都进切面里面
	public Object recordActionLog(ProceedingJoinPoint joinPoint) throws Throwable {

		// 执行方法之前做事 前置通知
		long startTime = System.currentTimeMillis(); 
		Object result = joinPoint.proceed(joinPoint.getArgs());
		long end = System.currentTimeMillis(); 
		try {
			addLog(joinPoint, startTime, end); // 记录日志
		}catch (Exception e) {
			e.printStackTrace(); 
		}
		return result;
	}
	private void addLog(ProceedingJoinPoint joinPoint, long startTime, long end) {
		// 执行方法之后做事 后置通知
		SysLog sysLog = new SysLog();
		
		// 将登录的对象从线程里面取出来*
		SysUser sysUser = (SysUser) SecurityUtils.getSubject().getPrincipal();
		sysLog.setUsername(sysUser.getUsername());
		
		//将所有的请求参数，从线程里面取出来（*****）
		ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = servletRequestAttributes.getRequest();
		sysLog.setIp(request.getRemoteAddr());
		
		// 得到方法的名称（***）
		MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
		Method method = methodSignature.getMethod();
		sysLog.setMethod(methodSignature.toString());

		ActionLog log = method.getAnnotation(ActionLog.class);
		sysLog.setOperation(log.value());
		sysLog.setTime(end-startTime);
		sysLog.setParams(JSONUtil.toJsonStr(joinPoint.getArgs()));
		sysLog.setCreateDate(LocalDateTime.now());
		sysLogService.save(sysLog);
	}
}
